package xyz.xpman.prisonerfitness.util;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;

import androidx.core.util.Consumer;
import androidx.exifinterface.media.ExifInterface;

import org.jetbrains.annotations.NotNull;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.List;


@SuppressWarnings("unused")
public class ImgUtil {


    private ImgUtil() { }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    public static Bitmap getAppropriateImg(
            @NotNull final Activity activity, int imgId) {

        return getAppropriateImg(activity, getDrawableImg(activity, imgId));
    }


    public static Bitmap getAppropriateImg(
            @NotNull final Activity activity, @NotNull Drawable drawable) {

        // 获取屏幕的宽和高
        Point win = ScreenUtil.getWindowsRealSize(activity);
        int screenWidth = win.x;
        int screenHeight = win.y;


        Point imageOption = getDrawableSize(drawable);
        int imageWidth = imageOption.x;
        int imageHeight = imageOption.y;


        // 图片的宽高除以屏幕的宽高，算出宽和高的缩放比例，取较小值作为图片的缩放比例
        float scaleX = (float) screenWidth / (float) imageWidth;
        float scaleY = (float) screenHeight / (float) imageHeight;


        // canvas: 575 * 1024
        // origin: 1810 * 3218
        // screen: 1080 * 2276
        // real: 1080 * 2400

        // 建立新的 bitmap ，其内容是对原 bitmap 的缩放后的图
        return bitmapScale(drawableToBitmap(drawable), scaleX, scaleY);
    }



/*    public static Options getImageSize(@NotNull String imgFileName) {
        Options opts = new Options();
        // 只请求图片宽高，不解析图片像素(请求图片属性但不申请内存，解析bitmap对象，该对象不占内存)
        opts.inJustDecodeBounds = true;
        boolean test = new File(imgFileName).exists();
        BitmapFactory.decodeFile(imgFileName, opts);

        return opts;
    }*/



    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



    public static Point getDrawableSize(@NotNull Drawable d) {
        return new Point(d.getMinimumWidth(), d.getMinimumHeight());
    }


    @SuppressLint("UseCompatLoadingForDrawables")
    public static Drawable getDrawableImg(@NotNull Context context, int imgId) {
        return context.getResources().getDrawable(imgId);
    }


    public static Drawable drawableToSampleSize(@NotNull Drawable drawable, int width, int height) {
        Rect rect = new Rect(0, 0, width, height);
        drawable.setBounds(rect);
        return drawable;
    }

/*    public static Drawable zoomDrawable(@NotNull Drawable drawable, int w, int h) {
        int width = drawable.getIntrinsicWidth();
        int height= drawable.getIntrinsicHeight();
        // drawable 转换成 bitmap
        Bitmap oldBmp = drawableToBitmap(drawable);
        // 创建操作图片用的 Matrix 对象
        Matrix matrix = new Matrix();
        // 计算缩放比例
        float scaleWidth = ((float)w / width);
        float scaleHeight = ((float)h / height);
        // 设置缩放比例
        matrix.postScale(scaleWidth, scaleHeight);
        // 建立新的 bitmap ，其内容是对原 bitmap 的缩放后的图
        Bitmap newBmp = Bitmap.createBitmap(oldBmp, 0, 0, width, height, matrix, true);


        // 把 bitmap 转换成 drawable 并返回
        return new BitmapDrawable(newBmp);
    }*/


    public static Bitmap drawableToBitmap(@NotNull Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    public static Drawable bitmapToDrawable(@NotNull Resources resources, @NotNull Bitmap bm) {
        return new BitmapDrawable(resources, bm);
    }


    // Bitmap.CompressFormat.TYPE: Bitmap.CompressFormat.PNG...
    public static boolean drawableToFile(@NotNull Drawable drawable,
                               @NotNull String filePath,
                               @NotNull Bitmap.CompressFormat format) {

        return BitmapUtil.writeBitmap(((BitmapDrawable) drawable).getBitmap(), filePath, format);
    }



    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -







    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



    public static void writeBitmapToFile(
            @NotNull String filePath, @NotNull Bitmap b, int quality) {

        try (FileOutputStream fos = new FileOutputStream(new File(filePath));
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {

            b.compress(Bitmap.CompressFormat.JPEG, quality, bos);
            bos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static Bitmap compressImage(@NotNull Bitmap image) {
        Bitmap bitmap = null;

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

            image.compress(Bitmap.CompressFormat.JPEG, 100, baos);

            bitmap = BitmapFactory.decodeStream(
                    new ByteArrayInputStream(baos.toByteArray()));

        } catch (OutOfMemoryError | IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 根据scale生成一张图片
     *
     * @param bitmap 图片
     * @param scaleX  等比缩放值
     * @return 比缩放图片
     */
    public static Bitmap bitmapScale(@NotNull Bitmap bitmap, float scaleX, float scaleY) {
        Matrix matrix = new Matrix();
        // 长和宽放大缩小的比例
        matrix.postScale(scaleX, scaleY);
//        matrix.postScale(scaleX, scaleX);
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }


    /**
     * 读取照片exif信息中的旋转角度
     *
     * @param path 照片路径
     * @return 角度
     */
    private static int readPictureDegree(String path) {
        if (TextUtils.isEmpty(path)) {
            return 0;
        }
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (Exception ignored) {
        }
        return degree;
    }


    private static Bitmap rotateBitmap(@NotNull Bitmap b, float rotateDegree) {
        Matrix matrix = new Matrix();
        matrix.postRotate(rotateDegree);
        return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
    }





    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



    public static void getImgByUrl(@NotNull String address,
                                   @NotNull Consumer<Bitmap> func) {

        if (StrKit.notBlank(address)) {
            getImgByUrl(Collections.singletonList(address), func);
        }
    }

    public static void getImgByUrl(@NotNull List<String> addresses,
                                   @NotNull Consumer<Bitmap> func) {

        if (addresses.isEmpty()) {
            return;
        }

        new Thread(() -> {
            for (String address : addresses) {
                Bitmap bitmap = getImgByUrlSyn(address);

                if (null == bitmap) {
                    break;
                }

                func.accept(bitmap);
            }
        }).start();
    }




    public static void getImgByUrlSyn(@NotNull String address,
                                   @NotNull Consumer<Bitmap> func) {

        if (StrKit.notBlank(address)) {
            getImgByUrlSyn(Collections.singletonList(address), func);
        }
    }

    public static Bitmap getImgByUrlSyn(@NotNull List<String> addresses) {

        if (addresses.isEmpty()) {
            return null;
        }


        for (String address : addresses) {
            Bitmap bitmap = getImgByUrlSyn(address);

            if (null != bitmap) {
                return bitmap;
            }
        }

        return null;
    }


    public static void getImgByUrlSyn(@NotNull List<String> addresses,
                                      @NotNull Consumer<Bitmap> func) {

        if (addresses.isEmpty()) {
            return;
        }

        for (String address : addresses) {
            Bitmap bitmap = getImgByUrlSyn(address);

            if (null == bitmap) {
                break;
            }

            func.accept(bitmap);
        }
    }

    /**
     * 同步获取图片，请使用异步包装
     * @param address 图片地址
     * @return 取得的图片
     */
    public static Bitmap getImgByUrlSyn(@NotNull String address) {
        Bitmap bitmap = null;

        try{
            // 获取url对应的图片资源，bitmap
            URL url = new URL(address);
            HttpURLConnection openConnection = (HttpURLConnection) url.openConnection();
            openConnection.setRequestMethod("GET");
            // 5ms
            openConnection.setConnectTimeout(10 * 1000);

            int code = openConnection.getResponseCode();
            if(code == 200){
                try (InputStream inputStream = openConnection.getInputStream()) {
                    bitmap = BitmapFactory.decodeStream(inputStream);
                } catch (IOException ignore) { }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

}
